package com.withoutwords.engine.comminication;


import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.withoutwords.engine.Game;
import com.withoutwords.engine.Round;
import com.withoutwords.engine.social.SocialUser;

import android.os.Bundle;

public class CommunicationManager {

	public static final String ServerURL = "http://www.faye2.com/bdonkalam/";// "www.bedonkalam.com";
	public static final String responseCode = "responseCode";
	public static final String roundCode = "round";
	public static final String userIdCode = "userId";
	public static final String gameIdCode = "gameId";
	public static final String usersCode = "users";
	// Singleton implementation
	private static CommunicationManager commMgrInstance = new CommunicationManager();

	public static CommunicationManager getCommnuicationManager() {
		return commMgrInstance;
	}

	private CommunicationManager() {

	}

	private void runAsyncHttpRequest(final String url, final Bundle paramsBundle,
			final boolean bGetMethod, final IHttpResponseHandler handler) {
		Thread th = new Thread(new Runnable() {

			@Override
			public void run() {
				String strURL = url;
				
				String strParams = "";
				if (paramsBundle != null)
					// adding parameters to URL
					strParams = formatURLParamterstoString(paramsBundle, bGetMethod);
				String method = HttpUtility.POST_METHOD;
				if (bGetMethod) {
					method = HttpUtility.GET_METHOD;
					strURL += strParams;
					strParams = "";
				}

				String res = HttpUtility.sendHttpRequest(strURL, strParams,
						method);
			

				handler.handleHttpResponse(res);

			}
		});

		th.start();
	}

	private void createGame(String strURL, Bundle data,
			final IServerResultListener listener) {


		runAsyncHttpRequest(strURL, data, true, new IHttpResponseHandler() {
			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						Bundle bundle = new Bundle();

						int index = response.indexOf(gameIdCode);
						if (index != -1) {
							bundle.putString(
									"game_id",
									response.substring(index
											+ gameIdCode.length() + 1));

						} else {
							listener.onRequestFailed(ServerRequests.createGame,
									response);
						}

						listener.onRequestSucceed(ServerRequests.createGame,
								bundle);
					} else {
						listener.onRequestFailed(ServerRequests.createGame,
								response);
					}
				}

			}
		});
	}

	private void getUserGames(String strURL, Bundle data,
			final IServerResultListener listener) {
		
		// HttpUtility util = new HttpUtility(new IHttpResponseHandler() {
		runAsyncHttpRequest(strURL, data, false, new IHttpResponseHandler() {
			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (true)// response != null && response == "0")
					{
						String jsonGame1 = "{" + "game_id : '222' ,"
								+ "private : false ,"
								+ "current_round : { round_id = '22244343' "
								+ "}," + "owner : { "
								+ "name :'Mona Shokrof' ,"
								+ "social_id : '545453453' ,"
								+ "social_network : 0 " + "} ," + "players : "
								+ "[ " + "{ " + "name :'Heba Hamdy' ,"
								+ "social_id : '5335453453' ,"
								+ "social_network : 0 " + "}," + "{"
								+ "name :'Ahmed Reda' ,"
								+ "social_id : '5335453453' ,"
								+ "social_network : 0 " + "}" + "]" + "}";

						String jsonGame2 = "{" + "game_id : '223' ,"
								+ "private : false ,"
								+ "current_round : { round_id = '22244343' "
								+ "}," + "owner : {"
								+ "name :'Mahmoud Fayek' ,"
								+ "social_id : '545453453' ,"
								+ "social_network : 0 " + "}," + "players : "
								+ "[" + "{" + "name :'Heba Sherif' ,"
								+ "social_id : '5335453453' ,"
								+ "social_network : 0 " + "}," + "{"
								+ "name :'Asmaa' ,"
								+ "social_id : '5335453453' ,"
								+ "social_network : 0 " + "}," + "{"
								+ "name :'Eman Hassan' ,"
								+ "social_id : '5335453453' ,"
								+ "social_network : 0 " + "}" + "]" + "}";

						ArrayList<Game> games = new ArrayList<Game>();
						try {
							Game newGame1 = new Game();

							newGame1.fromJSON(new JSONObject(jsonGame1));

							games.add(newGame1);
							Game newGame2 = new Game();
							newGame2.fromJSON(new JSONObject(jsonGame2));
							games.add(newGame2);
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						Bundle responseBundle = new Bundle();
						responseBundle.putSerializable("games", games);
						listener.onRequestSucceed(ServerRequests.getUserGames,
								responseBundle);
						// listener.onRequestSucceed(request, null);
					} else {

						listener.onRequestFailed(ServerRequests.getUserGames,
								response);
					}
				}

			}
		});

	}

	private void getRegisteredUser(String strURL, Bundle data,
			final IServerResultListener listener) {
		

		runAsyncHttpRequest(strURL, data, false, new IHttpResponseHandler() {
			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {

								index = response.indexOf(usersCode);
								if (index != -1) {
									String users = response.substring(index
											+ usersCode.length() + 1);
									try {
										JSONArray jsonArr = new JSONArray(
												users);
										ArrayList<SocialUser> registeredUsers = new ArrayList<SocialUser>();
										for (int i = 0; i < jsonArr.length(); i++) {
											SocialUser friend = new SocialUser();
											friend.fromJSON(jsonArr
													.getJSONObject(i));
											registeredUsers.add(friend);

										}
										Bundle bundle = new Bundle();
										bundle.putSerializable(usersCode,
												registeredUsers);

										listener.onRequestSucceed(
												ServerRequests.getRegisteredUser,
												bundle);
										return;
									} catch (JSONException e) {
										// TODO Auto-generated catch block
										e.printStackTrace();
									}
								}

							}
						}
						{
							listener.onRequestFailed(
									ServerRequests.getRegisteredUser, response);
						}
					}

				}
			}
		});

	}

	private void registerUser(String strURL, Bundle data,
			final IServerResultListener listener) {
		
		runAsyncHttpRequest(strURL, data, true, new IHttpResponseHandler() {

			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {

								index = response.indexOf(userIdCode);
								if (index != -1) {
									String userId = response.substring(index
											+ userIdCode.length() + 1);
									Bundle bundle = new Bundle();
									bundle.putString(userIdCode, userId);
									listener.onRequestSucceed(
											ServerRequests.registerUser, bundle);
									return;
								}
							}
						}

						listener.onRequestFailed(ServerRequests.registerUser,
								response);
					}
				}
			}
		});
	}

	private void joinGame(String strURL, Bundle data,
			final IServerResultListener listener) {
		
		runAsyncHttpRequest(strURL, data, true, new IHttpResponseHandler() {

			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {
								listener.onRequestSucceed(
										ServerRequests.joinGame, null);
								return;
							}
						}
						listener.onRequestFailed(ServerRequests.joinGame,
								response);

					}

				}
			}
		});
	}

	private void approveGuess(String strURL, Bundle data,
			final IServerResultListener listener) {
	
		runAsyncHttpRequest(strURL, data, true, new IHttpResponseHandler() {

			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {
								listener.onRequestSucceed(
										ServerRequests.aproveGuess, null);
								return;
							}
						}
						listener.onRequestFailed(ServerRequests.aproveGuess,
								response);

					}

				}
			}
		});
	}

	private void createRound(String strURL, Bundle data,
			final IServerResultListener listener) {
	
		runAsyncHttpRequest(strURL, data, true, new IHttpResponseHandler() {

			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {
								listener.onRequestSucceed(
										ServerRequests.createRound, null);
								return;
							}
						}
						listener.onRequestFailed(ServerRequests.createRound,
								response);
					}
				}

			}
		});
	}

	private void submitGuess(String strURL, Bundle data,
			final IServerResultListener listener) {
		
		runAsyncHttpRequest(strURL, data, true, new IHttpResponseHandler() {

			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {
								listener.onRequestSucceed(
										ServerRequests.SubmitGuess, null);
								return;
							}
						}
						listener.onRequestFailed(ServerRequests.SubmitGuess,
								response);
					}
				}

			}
		});
	}

	private void getCurrentRoundInfo(String strURL, Bundle data,
			final IServerResultListener listener) {
		
		runAsyncHttpRequest(strURL, data, true, new IHttpResponseHandler() {

			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {

								index = response.indexOf(roundCode);
								if (index != -1) {
									String roundJson = response.substring(index
											+ roundCode.length() + 1);
									Bundle bundle = new Bundle();
									Round r = new Round();
									try {
										r.fromJSON(new JSONObject(roundJson));
									} catch (JSONException e) {
										// TODO Auto-generated catch block
										e.printStackTrace();
									}
									bundle.putSerializable(roundCode, r);
									listener.onRequestSucceed(
											ServerRequests.getCurrentRoundInfo,
											bundle);
									return;
								}
							}
						}

						listener.onRequestFailed(
								ServerRequests.getCurrentRoundInfo, response);
					}
				}
			}
		});
	}

	private void sendActingData(String strURL, Bundle data,
			final IServerResultListener listener) {
		
		runAsyncHttpRequest(strURL, data, false, new IHttpResponseHandler() {

			@Override
			public void handleHttpResponse(String response) {
				if (listener != null) {
					if (response != null) {
						int index = response.indexOf(responseCode);
						if (index != -1) {
							int codeIndex = index + responseCode.length() + 1;
							String resCode = response.substring(codeIndex,
									codeIndex + 1);

							if (resCode.equalsIgnoreCase("0")) {
								listener.onRequestSucceed(
										ServerRequests.sendActingData, null);
							}
						}
						listener.onRequestFailed(ServerRequests.sendActingData,
								response);
					}
				}

			}
		});
	}

	public boolean request(final ServerRequests request, Bundle data,
			final IServerResultListener listener) {
		String strURL = ServerURL + request + ".php";
		switch (request) {
		case getUserGames: {
			getUserGames(strURL, data, listener);
			break;
		}
		case getRegisteredUser: {
			getRegisteredUser(strURL, data, listener);
			break;
		}
		case createGame: {

			createGame(strURL, data, listener);
			break;
		}
		case registerUser: {

			registerUser(strURL, data, listener);
			break;

		}
		case joinGame: {
			joinGame(strURL, data, listener);
			break;
		}
		case createRound: {
			createRound(strURL, data, listener);
			break;
		}
		case sendActingData: {
			sendActingData(strURL, data, listener);
			break;
		}
		case getCurrentRoundInfo: {
			getCurrentRoundInfo(strURL, data, listener);
			break;
		}
		case aproveGuess: {
			approveGuess(strURL, data, listener);
			break;
		}
		case SubmitGuess: {
			submitGuess(strURL, data, listener);
			break;
		}
		}
		return true;
	}

	String formatURLParamterstoString(Bundle params, boolean bgetrequest) {
		if (!params.isEmpty()) {
			String strParams = "";
			if (bgetrequest)
				strParams = "?";

			for (String key : params.keySet()) {
				try {
					String value = params.get(key).toString();
					if (value != null) {
						strParams += key + "="
								+ URLEncoder.encode(value, "utf-8");
						strParams += "&";
					}
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			// to remove the last &
			strParams = strParams.substring(0, strParams.length() - 1);

			return strParams;
		} else
			return "";
	}

}
